package com.sh.rpc.server.tcp;

import cn.hutool.core.util.IdUtil;

import com.sh.rpc.RpcApplication;
import com.sh.rpc.model.RpcRequest;
import com.sh.rpc.model.RpcResponse;
import com.sh.rpc.model.ServiceMetaInfo;
import com.sh.rpc.protocol.*;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * Tcp客户端 测试
 *
 * @author sh
 */
public class VertxTcpClient {

    // 发送请求响应
    public static RpcResponse doRequest(RpcRequest rpcRequest, ServiceMetaInfo serviceMetaInfo) throws ExecutionException, InterruptedException {
        Vertx vertx = Vertx.vertx();
        NetClient netClient = vertx.createNetClient();
        CompletableFuture<RpcResponse> responseFuture = new CompletableFuture<>();
        netClient.connect(serviceMetaInfo.getServicePort(), serviceMetaInfo.getServiceHost(),
                result -> {
                    if (!result.succeeded()) {
                        System.err.println("连接失败");
                        return;
                    }
                    NetSocket socket = result.result();
                    //  发送请求
                    // 先构造
                    ProtocolMessage<RpcRequest> protocolMessage = new ProtocolMessage<>();
                    ProtocolMessage.Header header = new ProtocolMessage.Header();
                    header.setMagic(ProtocolConstant.PROTOCOL_MAGIC);
                    header.setVersion(ProtocolConstant.PROTOCOL_VERSION);
                    String serializerTo = RpcApplication.getRpcConfig().getSerializer();  // 序列化方式  jdk  json、、
                    int serializerKey = ProtocolMessageSerializerEnum.getEnumByValue(serializerTo).getKey();  // 序列化器的编号
                    header.setSerializer((byte) serializerKey);
                    header.setType((byte) ProtocolMessageTypeEnum.REQUEST.getKey());
                    header.setRequestId(IdUtil.getSnowflakeNextId());
                    protocolMessage.setHeader(header);  // 设置头部
                    protocolMessage.setBody(rpcRequest);  // 设置请求体
                    // 编码
                    try {
                        Buffer encodeBuffer = ProtocolMessageEncoder.encode(protocolMessage);
                        socket.write(encodeBuffer);
                    } catch (Exception e) {
                        throw new RuntimeException("编码异常");
                    }


                    // 接收响应
                    TcpBufferHandlerWrapper bufferHandlerWrapper = new TcpBufferHandlerWrapper(
                            buffer -> {
                                try {
                                    ProtocolMessage<RpcResponse> rpcResponseProtocolMessage =
                                            (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decode(buffer);
                                    responseFuture.complete(rpcResponseProtocolMessage.getBody());
                                } catch (IOException e) {
                                    throw new RuntimeException("协议消息解码错误");
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            }
                    );
                    socket.handler(bufferHandlerWrapper);
                });
        RpcResponse rpcResponse = responseFuture.get();
        netClient.close();
        return rpcResponse;
    }


}
